package com.ckm.aop;

import com.alibaba.fastjson2.JSONObject;
import com.ckm.entity.WebLog;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

@Order(0)
@Aspect
@Component
@Slf4j
public class LogAspect {

    //@within 主要用于匹配类级别上应用了特定注解的类
    @Around("@annotation(com.ckm.annotation.LogInfo) || @within(com.ckm.annotation.LogInfo)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        WebLog webLog = new WebLog();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        webLog.setStartTime(format.format(new Date(startTime)));

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        Assert.notNull(requestAttributes,"请求不能为空");
        HttpServletRequest request = requestAttributes.getRequest();
        StringBuffer basePath = request.getRequestURL().delete(request.getRequestURL().indexOf(request.getRequestURI()), request.getRequestURL().length());
        webLog.setBasePath(basePath.toString());
        webLog.setUri(request.getRequestURI());
        webLog.setUrl(request.getRequestURL().toString());
        webLog.setMethod(request.getMethod());
        webLog.setIp(getIp(request));

        Object result = joinPoint.proceed();

        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        long endTime = System.currentTimeMillis();
        webLog.setSpendTime((int) (endTime-startTime));
        webLog.setInterfaceName(signature.getName());
        webLog.setParameter(getParameter(method,joinPoint.getArgs()));
        webLog.setResult(result);

        log.info("{}", JSONObject.from(webLog).toString());
        return result;
    }

    private Object getParameter(Method method,Object[] args){
        ArrayList<Object> list = new ArrayList<>();
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            //将RequestBody注解的参数作为请求参数
            Class<?> type = parameters[i].getType();
            if (type.equals(HttpServletRequest.class) || type.equals(HttpServletResponse.class)){
                continue;
            }else if (type.equals(MultipartFile.class)){
                continue;
            }
            RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
            if (requestBody!=null){
                list.add(args[i]);
                continue;
            }
            //将RequestParam注解的参数作为请求参数
            RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
            if (requestParam!=null){
                HashMap<String, Object> map = new HashMap<>();
                String key = parameters[i].getName();
                if (!requestParam.value().isEmpty()){
                    key = requestParam.value();
                }
                map.put(key,args[i]);
                list.add(map);
                continue;
            }

            list.add(args[i]);
        }
        if (list.isEmpty()){
            return null;
        }else if (list.size()==1){
            return list.getFirst();
        }else {
            return list;
        }
    }

    private String getIp(HttpServletRequest request){
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }
}
